.\"/*
.\" * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
.\" * See https://llvm.org/LICENSE.txt for license information.
.\" * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
.\" *
.\" */
.NS 16 "Register Classes"
.de DN
.nf
    \\*(cf\\$1\\*(rf
.fi
..
.de DA
.nf
	    \\*(cf\\$1\\*(rf
.fi
..
.sh 2 Overview
Two views of registers are used throughout the compiler:
.i generic
.i registers
and
.i machine
.i registers .
To facilitate retargeting, several classes of generic registers are
defined to hide the machine registers from various phases of the compiler.
Generic registers are mapped to machine registers with the likelihood
that more than one class of generic registers map to a single class of 
machine registers.
A generic register class exists for each of the register types seen by
the ILI:
address register, integer register (integers, booleans, char, etc.),
single precision register, and double precision register.
The generic register mappings
are primarily used by the expander and optimizer when
assigning global registers.
.lp
Depending on the target
register numbers, when used as operands to ILI, reflect either
actual machine register numbers or numbers which are mapped by
the code scheduler to actual machine numbers.
Registers can be used as arguments for calling intrinsics,
and as operands to register define and move ILI.  In the latter case,
these ILI are typically generated by the expander and optimizer
when registers have been assigned globally.
.sh 2 "Data Structures"
.sh 3 "Machine Register Table"
The target machine registers are divided into classes appropriate for
the target's architecture.
Each machine register set has the following properities:
.np
each class is expressed as a set of increasing order of numbers.
.np
the scratch registers are defined by the code scheduler
.np
the global registers are allocated either in decreasing or increasing
order from a given point.
.np
the scratch registers that can be changed by a
procedure and intrinsic.
.lp
A machine register table is used to define the classes of machine registers,
where there is one entry for each class.
A table entry is defined by the following C structure declaration:
.ne 11
.CS

    typedef struct {
        char min;
        char max;
        char first_global;
        char last_global;
        char next_global;
        char nused;
    } MACH_REG;
.CE
.nr ii \w'\f(CWfirst_global\fP'+2n
.ip \f(CWmin\fP
minimum register number of the set.
.ip \f(CWmax\fP
maximum register number of the set (the set is defined by the closed
interval \f(CW[min..max]\fP).
.ip \f(CWfirst_global\fP
the first register number that can be global register.
.ip \f(CWlast_global\fP
the last register number that can be global.
.ip \f(CWnext_global\fP
the next register number that can be globally assigned.
In the event that not all of the registers in the global set are assigned
by the expander or optimizer,
the scheduler may use the global registers not assigned as
.i scratch
registers.
.ip \f(CWnused\fP
the number of global registers assigned by the expander or optimizer.
.nr 5n
.lp
All but the fields \f(CWnext_global\fP and \f(CWnused\fP are statically
initialized; \f(CWnext_global\fP and \f(CWnused\fP
are modified when registers are allocated globally
during the expander and optimizer phases.
.lp
It is possible that a machine's registers cannot be expressed
as the closed interval \f(CW[min .. max]\fP.
If this occurs, the machine register table will describe
"pseudo" machine registers which adhere to the above properties.
These pseudo machine registers would be mapped to the actual machine registers.
The ILI, expander, and optimizer would still refer to the registers from
the machine register table.
The scheduler would use the pseudo to machine register mapping when it's
neccessary to refer to an actual machine register.
.sh 3 "Generic Register Table"
The generic registers are divided into classes of registers which correspond
to the types of the registers seen by the ILI.
The mapping of generic registers to machine registers is described in
the generic register table.
Each table entry not only describes the mapping but
provides information regarding global register allocation.
Each table entry is defined by the following C structure declaration:
.ne 8
.CS

typedef struct {
    char      max;
    char      nused;
    char      joined;
    int       rcand;
    MACH_REG *mach_reg;
    INT       const_flag;
} REG;
.CE
.nr ii \w'\f(CWmach_reg\fP'+2n
.ip \f(CWmax\fP
the maximum number of registers that can be globally assigned.
.ip \f(CWnused\fP
the number of registers globally assigned.
.ip \f(CWjoined\fP
flag indicating that the registers are formed from multiple
machine registers.
.ip \f(CWrcand\fP
list of global register candidates.
.ip \f(CWmach_reg\fP
pointer to the machine register table entry of the machine registers
to which the generic class maps.
.ip \f(CWconst_flag\fP
a flag word which controls the assignment of constants to registers.
.nr 5n
The fields \f(CWmax\fP, \f(CWjoined\fP, \f(CWmach_reg\fP,
and \f(CWconst_flag\fP are statically initialized;
fields \f(CWnused\fP and \f(CWrcand\fP in module
.i machreg.c
are modified when registers are allocated globally
during the expander and optimizer phases.
.sh 2 "Processing"
The file
.i machreg.h
contains the specifics for the target machine's registers such as
definitions for the \f(CWmach_reg\fP
structure, external declarations for the functions used to access
the structure, and
macro definitions used to represent various pieces of the machine
registers.
When constructing
.i machreg.h ,
certain macros must be present: 
those which deal with register arguments and
those which describe the machine registers.
Argument macros are present which provided the register numbers for
accessing
.i argument
.i registers 
where the arguments to the macros are machine dependent.
There is one macro for each register type:
.ip AR(i)
define an address register
.ip IR(i)
define a integer register
.ip SP(i)
define a single precision register for argument
.ip DP(i)
define a double precision register for argument
.ip ISP(i)
define a single precision register for an imaginary argument
.ip IDP(i)
define a double precision register for an imaginary argument
.sh 3 "Machine Register Macros"
Special macros are used for defining the global registers in each
of the unique register classes (the macro
.cw MR_UNIQ
gives the number of unique classes).
For each global set, the lower and upper bounds are specified in the
form
.cw MR_L<i>
to
.cw MR_U<i> ,
where <i> = 1 to
.cw MR_UNIQ .
For example, if there are 2 unique classes, then the interval defined
by macros
.cw MR_L1
to
.cw MR_U1
defines
the global registers for set 1 and macros
.cw MR_L2
to
.cw MR_U2
defines
the global registers for set 2.
Note that the file
.i machregdf.h
uses these macros to data initialize the
.cw mach_reg
table.
.lp
The macro,
.cw MR_NUMGLB ,
defines the total number of global registers for the machine.
This macro is used by the optimizer to declare space for its
global register history data structures.
.lp
The macro GR_THRESHOLD defines the count which a candidate must
exceed before it's assigned a register.
.sh 2 "Program Units"
The register module is composed of the C files
.i register.c
and
.i machreg.c . 
The file
.i register.c
contains the following routines:
.nr ii 5n
.lp
.CS
void reg_init()
.CE
.ip
This function initializes the register information for a function
or subprogram which is passed on to the code generator and assembler.
.lp
.CS
void addrcand(ili)
int ili;
.CE
.ip
Add an ili to its register candidate list.
.lp
.CS
void dmprcand()
.CE
.ip
Dump the register candidate lists.
.lp
.CS
void dmprat(rat)
int rat;
.CE
.ip
Dump the register assigned table indexed by 
.cw rat .
.lp
.CS
int getrcand(candl)
int candl;
.CE
.ip
Gets a register candidate for the list \f(CWcandl\fP.
.lp
.CS
void storedums(bih, rat)
int bih, rat;
.CE
.ip
Generates stores of the registers in the table \f(CW\fP
assigned to Fortran dummy arguments.
These stores are added to the block located by
the block information header, \f(CWbih\fP.
.lp
.CS
void mkrtemp_init()
.CE
.ip
Initialize the register temporary areas; this is done when
unique temps are desired during the processing of a
unit (i.e., for an ILM block) but are still
shared with the previous unit.
.lp
.CS
int mkrtemp(ili)
int ili;
.CE
.ip
Gets a register temporary whose register type is based on
the type of \f(CWili\fP.
.lp
.CS
void mkrtemp_end()
.CE
.ip
Routine called at the end of processing a function to
so that the temps created for the next function are
unique. 
.lp
.CS
void mkrtemp_update(rtemp)
short rtemp[];
.CE
.ip
Update the maximum values for the register temporaries whose
information is stored in \f(CWrtemp\fP.
.lp
.CS
void mkrtemp_copy(rtemp)
short rtemp[];
.CE
.ip
Copy the maximum values of the temporaries which have been
allocated to the area \f(CWrtemp\fP.
.lp
.CS
int assn_rtemp(ili)
int ili;
.CE
.ip
Create a register temporary for \f(CWili\fP and record
the temporary and the ili in the appropriate register
candidate list.
.lp
.nr 5n
.The file
.i machreg.c
contains the following routines:
.nr ii 5n
.lp
.CS
void mr_init()
.CE
.ip
This function initializes the fields of the
structures,
.cw mach_reg
and
.cw reg ,
for the current function or subprogram
which are not statically initialized.
.lp
.CS
int mr_getreg(rtype)
int rtype;
.CE
.ip
This function returns a global machine register number
for the register type specified by
.cw rtype .
If one is not available,
.cw MR_NOREG
is returned.
.lp
.CS
int mr_gindex(rtype, reg)
int rtype, reg;
.CE
.ip
This function maps a register type,
.cw rtype ,
and a global machine register number,
.cw reg ,
to an index value in the range
.cw 0..MR_NUMGLB-1 .
This routine is aware that certain register types may map to the
same machine register set.
This routine provides a mechanism for ensuring that the history
of a machine register can be kept regardless of the many to one register
type mapping.
.lp
.nr 5n
